import 'xterm/css/xterm.css'

import type { AxiosProgressEvent } from 'axios'
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'

import type { CertLogModel } from '@/apis/model/cert'

export type TitleKey = 'processing' | 'success' | 'error'
export const defaultTitleMap: Record<TitleKey, string> = {
  processing: '正在连接中....',
  success: '连接成功',
  error: '连接失败'
}

export interface UseTerminalOptions {
  api: (
    data: CertLogModel,
    onDownloadProgress: (progressEvent: AxiosProgressEvent) => void
  ) => Promise<any>
  body: Record<string, any>
  titleMap?: Record<TitleKey, string>
  immediate?: boolean
  // 字段
  commandFiled?: string
}

export const useTerminal = ({
  api,
  immediate,
  body
}: // titleMap = defaultTitleMap
UseTerminalOptions) => {
  const el = ref<HTMLElement>()
  const termSize = reactive({
    rows: 24,
    cols: 80
  })
  const fitAddon = new FitAddon()
  const dotStatus = ref<TitleKey>('processing')
  const title = computed(() => {
    // return merge(defaultTitleMap, titleMap)[dotStatus.value]
    return '远程安装'
  })
  const terminalInstance = ref<Terminal>()
  const classNames = computed(() => [
    'web-terminal__modal',
    `is-${dotStatus.value}`
    // 'is-processing'
  ])

  const dispose = () => {
    try {
      if (terminalInstance.value?.dispose) terminalInstance.value?.dispose?.()
    } catch (_) {}
    dotStatus.value = 'processing'
  }
  const isEnd = ref(false) // 为true时则表示申请证书成功
  const loading = ref(false)
  const txtContent = ref('')
  const _fetch = (data?: any) => {
    if (!api) {
      console.error('参数 api 必选')
      return
    }
    reset()
    loading.value = true
    api(
      {
        id: body.id || data.id,
        xterm_weight: 120,
        xterm_height: 120
      },
      (progressEvent: AxiosProgressEvent) => {
        if (dotStatus.value === 'processing') {
          dotStatus.value = 'success'
        }
        const resp = progressEvent.event?.currentTarget?.response
        if (resp) {
          terminalInstance.value?.write(resp)
        }
      }
    )
      .then(res => {
        isEnd.value = res.data.is_end
        txtContent.value = res.data.message
        // terminalInstance.value?.write('\x1b[31m') // 设置文本颜色为红色
        terminalInstance.value?.write(res.data.message)
        if (isEnd.value) dotStatus.value = 'success'
        nextTick(() => {
          fitAddon.fit()
        })
      })
      .finally(() => (loading.value = false))
      .catch(() => {
        dotStatus.value = 'error'
        // terminalInstance.value?.write(err.message)
      })
  }

  const createTerminalInstance = (data: CertLogModel) => {
    if (!el.value) {
      console.error('请先绑定 Terminal 元素')
      return
    }
    terminalInstance.value = new Terminal({
      lineHeight: 1.2,
      fontSize: 14,
      convertEol: true,
      fontFamily: "Monaco, Menlo, Consolas, 'Courier New', monospace",
      scrollback: 800,
      cursorBlink: false, // 光标闪烁
      cursorInactiveStyle: undefined, //光标样式
      disableStdin: true, //是否应禁用输入。
      rightClickSelectsWord: true,
      logLevel: 'off',
      drawBoldTextInBrightColors: true,
      wordSeparator: ' ',
      theme: {
        foreground: '#fff', //字体
        background: '#1D2129', //背景色
        cursor: 'help', //设置光标,
        selectionBackground: 'rgba(255,255,255,.3)', //选中背景
        selectionForeground: 'white' //选中文字
      }
    })
    terminalInstance.value?.loadAddon(fitAddon)

    fitAddon.fit()

    terminalInstance.value?.open(el.value)

    terminalInstance.value?.focus()
    dotStatus.value = 'processing'

    termSize.rows = terminalInstance.value?.rows || 24
    termSize.cols = terminalInstance.value?.cols || 80

    _fetch(data)
  }

  const run = (data?: any) => {
    createTerminalInstance(data)
  }
  const request = (data: CertLogModel) => {
    _fetch(data)
  }
  const reset = () => {
    terminalInstance.value?.reset()
    isEnd.value = false
  }
  nextTick(() => {
    if (immediate) run()
  })

  return {
    el,
    run,
    request,
    title,
    loading,
    dispose,
    classNames,
    reset,
    isEnd,
    txtContent
  }
}
